package com.aisino.mplearning.interceptor;

import com.aisino.mplearning.annotation.IgnoreDataAccess;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import lombok.SneakyThrows;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.QueryTimeoutException;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.sql.SQLException;

/**
 * @author guochuantao
 * @version 1.0
 * @description 数据库数据权限拦截器
 * @since 2024/8/29 下午4:24
 */
@Component
public class DataAccessInterceptor implements InnerInterceptor {
    /**
     * 日志
     */
    private static Logger log = LoggerFactory.getLogger(DataAccessInterceptor.class);

    /**
     * 通过线程变量控制service是否采用数据权限
     */
    public static ThreadLocal<Boolean> isIgnoreDataAccessHolder = new ThreadLocal<>();

    /**
     * 查询前
     *
     * @param executor      执行
     * @param ms            消息
     * @param parameter     参数
     * @param rowBounds     行边界
     * @param resultHandler 结果处理程序
     * @param boundSql      绑定 SQL
     * @throws SQLException sql异常
     */
    @SneakyThrows //自动声明异常
    @Override
    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
        log.error("查询前的拦截方法执行了...");
        System.out.println("executor = " + executor);
        System.out.println("ms = " + ms);
        System.out.println("parameter = " + parameter);
        System.out.println("rowBounds = " + rowBounds);
        System.out.println("resultHandler = " + resultHandler);
        System.out.println("boundSql = " + boundSql);

        if (isIgnoreDataAccessHolder.get() != null && isIgnoreDataAccessHolder.get()) {
            isIgnoreDataAccessHolder.remove();
            return;
        }

        //判断是否有IgnoreDataAccess注解
        Class<?> aClass = Class.forName(ms.getId().substring(0, ms.getId().lastIndexOf(".")));
        String methodName = ms.getId().substring(ms.getId().lastIndexOf(".") + 1);
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method method : declaredMethods) {
            if (method.getName().equals(methodName)) {
                if (method.isAnnotationPresent(IgnoreDataAccess.class)) {
                    IgnoreDataAccess annotation = method.getAnnotation(IgnoreDataAccess.class);
                    if (annotation.isIgnore()) {
                        return;
                    }
                }
                break;
            }
        }

        log.error("忽略权限逻辑没有执行....");

        //权限控制模拟
        throw new QueryTimeoutException("无权限执行数据库操作");

        // InnerInterceptor.super.beforeQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql);
    }
}
